package main

import (
	"bytes"
	"context"
	"crypto/cipher"
	"crypto/des"
	"crypto/md5"
	"flag"
	"fmt"
	appsv1 "k8s.io/api/apps/v1"
	apiv1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/util/retry"
)

// 初始化并加载kubeconfi文件配置
func main() {
	var kubeconfig *string
	//if home := homedir.HomeDir(); home != "" {
	//	kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "kubeconfig"), "(optional) absolute path to the kubeconfig file")
	//} else {
	kubeconfig = flag.String("kubeconfig", "./kubeconfig", "absolute path to the kubeconfig file")
	//}
	flag.Parse()

    //查询k8s集群版本号、node、default命名空间pod资源、default命名空间deployment资源
	getk8s(kubeconfig)
	//修改k8s集群default命名空间deployment资源应用副本数或镜像版本
	//updatedeployment(kubeconfig)
	//删除一个deployment
	//deletedeployments(kubeconfig)
	//删除一个svc
	//deletesvc(kubeconfig)
	//time.Sleep(30 * time.Second)

	//创建一个deployment
	//createdeployment(kubeconfig)
	//创建一个svc
	//createsvc(kubeconfig)

	//arr := []string{"zhangsan", "张三", "18022334281"}
	//orig := strings.Join(arr, ",")
	//fmt.Println("checkData：", orig)
	//md5byte := GetStringMd5(orig)
	////orig := "c8b7b2ff5f9c9155bb5e82ffb69a57b8"
	//key, _ := base64.StdEncoding.DecodeString("bGVhcm5fa2V5")
	//fmt.Println("key：", string(key))
	//fmt.Println("原文：", orig)
	//fmt.Println("原文md5：", hex.EncodeToString(md5byte))
	//
	//encryptCode, _ := DesEncrypt(md5byte, key)
	//fmt.Println("密文：", hex.EncodeToString(encryptCode))
	//
	//decryptCode, _ := DesDecrypt(encryptCode, key)
	//fmt.Println("解密结果：",hex.EncodeToString(decryptCode))
}

// 查询集群资源，namespace、pod、node、deployment
func getk8s(kubeconfig *string){
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}
    // create the clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}
	fmt.Println("查询k8s版本：")
	version, err := clientset.ServerVersion()
	fmt.Println("version=", version)
	fmt.Println("*******************************************************")
	fmt.Println("查询k8s集群命名空间：")
	list, _ := clientset.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
	for _, item := range list.Items {
		fmt.Println(item.Name)
	}
	fmt.Println("*******************************************************")
	fmt.Println("查询k8s集群节点资源：")
	//fmt.Println("node list ")
	nodeList1, _ := clientset.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{})
	for _, item := range nodeList1.Items {
		fmt.Println(item.Name)
	}
	fmt.Println("*******************************************************")
	fmt.Println("查询k8s集群default命名空间pod资源：")
	//fmt.Println("pod list in default")
	list1, _ := clientset.CoreV1().Pods("default").List(context.Background(), metav1.ListOptions{})
	for _, item := range list1.Items {
		fmt.Println(item.Name)
	}
	fmt.Println("*******************************************************")
	fmt.Println("查询k8s集群default命名空间deployment资源：")
	//fmt.Println("deployment list in default")
	deploymentList1, _ := clientset.AppsV1().Deployments("default").List(context.Background(), metav1.ListOptions{})
	for _, item := range deploymentList1.Items {
		fmt.Println(item.Name)
	}
}
func int32Ptr(i int32) *int32 { return &i }

// 修改deployment
func updatedeployment(kubeconfig *string)  {
	fmt.Println("*******************************************************")
	fmt.Println("修改k8s集群default命名空间deployment资源nginx-test副本数或镜像版本：")
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err)
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err)
	}
	//尝试更新资源
	retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
		//获取Get（）返回的“result"
		deploymentsClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault)
		result, getErr := deploymentsClient.Get(context.Background(), "nginx-test", metav1.GetOptions{})
		if getErr != nil {
			panic(fmt.Errorf("Failed to get latest version of Deployment: %v", getErr))
		}
		result.Spec.Replicas = int32Ptr(2)                                       // change replica count
		//result.Spec.Template.Spec.Containers[0].Image = "nginx:1.19.6" // change nginx version
		_,updateErr := deploymentsClient.Update(context.Background(), result, metav1.UpdateOptions{})
		return updateErr
	})
	if retryErr != nil {
		panic(fmt.Errorf("Update failed: %v", retryErr))
	}
	fmt.Println("Updated deployment success.")
}

// 创建一个deployment
func createdeployment(kubeconfig *string)  {

	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err)
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err)
	}

	deploymentsClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault)
	// Create Deployment
	deployment := &appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name: "nginx-test",
		},
		Spec: appsv1.DeploymentSpec{
			Replicas: int32Ptr(1),
			Selector: &metav1.LabelSelector{
				MatchLabels: map[string]string{
					"app": "nginx-test",
				},
			},
			Template: apiv1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{
						"app": "nginx-test",
					},
				},
				Spec: apiv1.PodSpec{
					Containers: []apiv1.Container{
						{
							Name:  "web",
							Image: "nginx:1.19.6",
							Ports: []apiv1.ContainerPort{
								{
									Name:          "http",
									Protocol:      apiv1.ProtocolTCP,
									ContainerPort: 80,
								},
							},
						},
					},
				},
			},
		},
	}
	fmt.Println("Creating deployment...")
	result, err := deploymentsClient.Create(context.Background(), deployment, metav1.CreateOptions{})
	if err != nil {
		//panic(err)
	}
	fmt.Printf("Created deployment %q.\n", result.GetObjectMeta().GetName())
}

// 创建一个Service
func createsvc(kubeconfig *string)  {
	config, _ := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	clientset, _ := kubernetes.NewForConfig(config)

	namespace := "default"
	var targetPort intstr.IntOrString
	targetPort.IntVal = 80

	service := &apiv1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Name: "nginx-test",
			Labels: map[string]string{
				"app": "nginx-test",
			},
		},
		Spec: apiv1.ServiceSpec{
			Selector: map[string]string{
				"app": "nginx-test",
			},
			Type: "NodePort",

			Ports: []apiv1.ServicePort{
				{
					Name:     "http",
					Port:     80,
					NodePort: 30082,
					TargetPort: targetPort,
					Protocol: apiv1.ProtocolTCP,
				},
			},
		},
	}
	fmt.Println("Creating svc...")
	result, err := clientset.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{})
	if err != nil {
		//panic(err)
	}
	fmt.Printf("Created svc %q.\n", result.GetObjectMeta().GetName())

}

// 删除一个deployment
func deletedeployments(kubeconfig *string){
	fmt.Println("*******************************************************")
	fmt.Println("删除k8s集群default命名空间deployment名为nginx-demo资源：")
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}

	// create the clientset
	clientset, err := kubernetes.NewForConfig(config)
	deploymentsClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault)
	deletePolicy := metav1.DeletePropagationForeground
	if err := deploymentsClient.Delete(context.Background(), "nginx-test", metav1.DeleteOptions{
		PropagationPolicy: &deletePolicy,
	}); err != nil {
		//anic(err)
	}
	fmt.Println("Deleted deployment nginx-demo success. ")
}

// 删除一个Service
func deletesvc(kubeconfig *string){
	fmt.Println("*******************************************************")
	fmt.Println("删除k8s集群default命名空间svc名为nginx-demo资源：")
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}

	// create the clientset
	clientset, err := kubernetes.NewForConfig(config)
	svcClient := clientset.CoreV1().Services(apiv1.NamespaceDefault)
	deletePolicy := metav1.DeletePropagationForeground
	if err := svcClient.Delete(context.Background(), "nginx-test", metav1.DeleteOptions{
		PropagationPolicy: &deletePolicy,
	}); err != nil {
		//panic(err)
	}
	fmt.Println("Deleted svc nginx-demo success. \n")
}
//加密
func DesEncrypt(origData []byte, key []byte) ([]byte, error) {
	if len(key) > 8 {
		key = key[:8]
	}
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	origData = PKCS5Padding(origData, block.BlockSize())
	blockMode := cipher.NewCBCEncrypter(block, key)
	crypted := make([]byte, len(origData))
	blockMode.CryptBlocks(crypted, origData)
	return crypted, nil
}

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

//解密
func DesDecrypt(crypted, key []byte) ([]byte, error) {
	if len(key) > 8 {
		key = key[:8]
	}
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockMode := cipher.NewCBCDecrypter(block, key)
	origData := make([]byte, len(crypted))
	// origData := crypted
	blockMode.CryptBlocks(origData, crypted)
	origData = PKCS5UnPadding(origData)
	// origData = ZeroUnPadding(origData)
	return origData, nil
}

func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	// 去掉最后一个字节 unpadding 次
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}
//计算MD5
func GetStringMd5(s string) []byte {
	md5 := md5.New()
	md5.Write([]byte(s))
	//md5Str := hex.EncodeToString(md5.Sum(nil))
	return md5.Sum(nil)
}
//计算MD5
func GetByteMd5(s []byte) []byte {
	md5 := md5.New()
	md5.Write(s)
	//md5Str := hex.EncodeToString(md5.Sum(nil))
	return md5.Sum(nil)
}